varying vec3 N;
varying vec3 v;

uniform sampler2DRect tex ;
uniform int draw_face ;


vec4 light_model (vec4 color)
{
		vec3 L = normalize(gl_LightSource[0].position.xyz - v);   
		vec3 E = normalize(-v); // we are in Eye Coordinates, so EyePos is (0,0,0)  
		vec3 R = normalize(-reflect(L,N));  
	 
		//calculate Ambient Term:  
		vec4 Iamb = gl_FrontLightProduct[0].ambient;    

		//calculate Diffuse Term:  
		vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0);    
	   
		// calculate Specular Term:
		vec4 Ispec = gl_FrontLightProduct[0].specular 
					* pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess);
					
		color = color * (gl_FrontLightModelProduct.sceneColor + Iamb + Idiff + Ispec);  
		return color ;
}
//xoffset yoffset
const float x_off = 1.0 ;
const float y_off = 1.0 ;

/*Texture coordinates of triangle are
(0,0),(c,0) and (k,h)*/
void transform (int res, in vec2 st, in	vec2 vc[3], out vec2 p0, out vec2 p1, out vec2 p2, 
	 out int idx0, out int idx1, out int idx2)
{
	vec2 origin = vc[0] ;
	vc[0] = vc[0] - origin ; 	vc[1] = vc[1] - origin ; 	vc[2] = vc[2] - origin ;
	float c = vc[1].x ;
	float k = vc[2].x ; float h = vc[2].y; 

	vec2 p [3]; 
	int idx[3] ;
	float s = st.s - origin.x;
	float t = st.t - origin.y;

	s = s / c ;
	t = t / h ;	
	s = s - k / c * t; /* Skew Transformation */

	float offset = 1.0 / float (res);
	int x_idx = int (s / offset) ;
	int y_idx = int (t / offset) ;
	
	
    if (s + t < float (x_idx + y_idx + 1) * offset)
    {		
		int x_, y_;

		p[0] = vec2( float(x_idx) * offset, float(y_idx + 1) * offset);
		p[1] = vec2(float(x_idx + 1) * offset,float( y_idx) * offset);
		p[2] = vec2(float(x_idx)  * offset, float(y_idx) * offset);

		x_ = res - x_idx - (y_idx + 1);
		y_ = x_idx; 
		idx[0] = (2*res + 3 - x_) * x_ / 2 + y_ ;

		x_ = res - (x_idx + 1) - (y_idx );
		y_ = x_idx + 1; 
		idx[1] = (2*res + 3 - x_) * x_ / 2 + y_ ;
		
		x_ = res - x_idx - (y_idx );
		y_ = x_idx; 
		idx[2] = (2*res + 3 - x_) * x_ / 2 + y_ ;
		
    }
    else
    {
		int x_, y_;
        p[0] = vec2(float(x_idx+1) * offset, float(y_idx ) * offset);
        p[1] = vec2(float(x_idx ) * offset, float(y_idx+1) * offset);
		p[2] = vec2(float(x_idx +1) * offset,float(y_idx+1) * offset);

		x_ = res - (x_idx  + 1)- (y_idx );
		y_ = x_idx + 1; 
		idx[0] = (2*res + 3 - x_) * x_ / 2 + y_ ;

		x_ = res - (x_idx ) - (y_idx +1);
		y_ = x_idx ; 
		idx[1] = (2*res + 3 - x_) * x_ / 2 + y_ ;

		x_ = res - (x_idx + 1) - (y_idx +1);
		y_ = x_idx + 1; 
		idx[2] = (2*res + 3 - x_) * x_ / 2 + y_ ;

    }
	
	p[0].x = p[0].x + k / c * p[0].y;  p[0].x = p[0].x * c ; p[0].y = p[0].y * h ; 
	p[1].x = p[1].x + k / c * p[1].y;  p[1].x = p[1].x * c ; p[1].y = p[1].y * h ;
	p[2].x = p[2].x + k / c * p[2].y;  p[2].x = p[2].x * c ; p[2].y = p[2].y * h ;


	p0 = p[0] + origin ; 
	p1 = p[1] + origin ;
	p2 = p[2] + origin ;

	idx0 = idx[0] ; 	idx1 = idx[1] ; 	idx2 = idx[2] ;
}

vec4 get_color (in int idx)
{
	const float color_offset = 4.0;	
	return texture2DRect (tex, vec2 (gl_TexCoord[0].s + (color_offset + float(idx)) * x_off, gl_TexCoord[0].t));
}

vec4 nearest (in vec2 st, in vec2 p[3], in int idx [3])
{
	vec4 c ;
	float dis1, dis2, dis3;
	dis1 = distance (st, p[0]);
	dis2 = distance (st, p[1]);
	dis3 = distance (st, p[2]);

	if (dis1 < dis2 && 
	   dis1 < dis3)
	{
		c = get_color(idx[0]);
	}
	else if (dis2 < dis1 && 
	   dis2 < dis3)
	{
		c = get_color(idx[1]); 
	}
	else
	{
		c = get_color(idx[2]);
	}
	return c;
}

float det3 (in mat3 m)
{
	float det = m[0][0] *(m[2][2]*m[1][1] - m[2][1]* m[1][2]) 
			- m[1][0] * (m[2][2]*m[0][1] - m[2][1]* m[0][2])
			+ m[2][0] * (m[1][2]*m[0][1] - m[1][1]* m[0][2]);
	return det ;
}

mat3 inverse3 (in mat3 m)
{
	float rdet = float(1.0) / det3(m);
	mat3 invm ;
	invm[0][0] =   rdet * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) ;
	invm[0][1] = - rdet * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) ;
	invm[0][2] =   rdet * (m[0][1] * m[1][2] - m[0][2] * m[1][1]) ;

	invm[1][0] = - rdet * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) ;
	invm[1][1] =   rdet * (m[0][0] * m[2][2] - m[0][2] * m[2][0]) ;
	invm[1][2] = - rdet * (m[0][0] * m[1][2] - m[0][2] * m[1][0]) ;

	invm[2][0] =   rdet * (m[1][0] * m[2][1] - m[1][1] * m[2][0]) ;
	invm[2][1] = - rdet * (m[0][0] * m[2][1] - m[0][1] * m[2][0]) ;
	invm[2][2] =   rdet * (m[0][0] * m[1][1] - m[0][1] * m[1][0]) ;
	return invm;
}

vec4 linear (in vec2 st, in vec2 p[3], in int idx [3])
{
	mat3 m =  mat3(p[0].x , p[0].y, 1.0, p[1].x, p[1].y, 1.0, p[2].x, p[2].y, 1.0) ;

	mat3 invm = inverse3(m);
	vec3 bc = invm * vec3(st.s, st.t, 1);
	vec4 c ;
//	c = get_color(idx[0]) * bc.x + get_color(idx[1]) * bc.y + get_color(idx[2]) * (1.0f - bc.x - bc.y);
	if (abs (bc.z) > abs(bc.x) )
	{
		if (abs(bc.z) > abs(bc.y))
	    		c = get_color(idx[0]) * bc.x + get_color(idx[1]) * bc.y + get_color(idx[2]) * (1.0f - bc.x - bc.y);
		else c = get_color(idx[0]) * bc.x + get_color(idx[1]) * (1.0f - bc.x- bc.z) + get_color(idx[2]) * bc.z;
	}	
	else
	{
		if (abs(bc.x) > abs (bc.y))
			c = get_color(idx[0]) * (1.0f - bc.y - bc.z) + get_color(idx[1]) * bc.y + get_color(idx[2]) * bc.z;
		else c = get_color(idx[0]) * bc.x + get_color(idx[1]) * (1.0f - bc.x- bc.z) + get_color(idx[2]) * bc.z;
	}
	return c;
}

void main()
{
	vec4 color ;
	if (draw_face == 1)
	{
	/*
	   //gl_FragColor = vec4(1.0,0.0,0.0,1.0) ; //nearest(st, p,idx);
	   // Sampling The Texture And Passing It To The Frame Buffer
       
	   // gl_FragColor = color ;
	  //vec4 color = texture2DRect(tex,gl_TexCoord[0].st);
		vec4 color = vec4(1.0, 0.0, 0.0, 1.0); //linear(st, p,idx);
		gl_FragColor = light_model (color);
	*/

	vec4 v_res = texture2DRect (tex, vec2 (gl_TexCoord[0].s, gl_TexCoord[0].t));
	int res = int(v_res[0]);
	
	//Get three vertex texcoord
	vec4 vertex[3];
	vertex[0] = texture2DRect (tex, vec2 (gl_TexCoord[0].s + 1.0f * x_off, gl_TexCoord[0].t));
	vertex[1] = texture2DRect (tex, vec2 (gl_TexCoord[0].s + 2.0f * x_off, gl_TexCoord[0].t));
	vertex[2] = texture2DRect (tex, vec2 (gl_TexCoord[0].s + 3.0f * x_off, gl_TexCoord[0].t));
	

	
	vec2 texcoord = gl_TexCoord[0].st ;
	vec2 vcoord[3];
	vcoord[0] = vec2(vertex[0].x, vertex[0].y) ; 
	vcoord[1] = vec2(vertex[1].x, vertex[1].y) ; 
	vcoord[2] = vec2(vertex[2].x, vertex[2].y) ;

	vec2 p[3];
	int idx[3];
	transform (res, gl_TexCoord[0].st, vcoord, p[0], p[1], p[2], idx[0], idx[1], idx[2]);

//	color = nearest (gl_TexCoord[0].st, p, idx);
	color = linear (gl_TexCoord[0].st, p, idx);

	
	}
	else 
	{
		color = gl_Color ;		
	}
	gl_FragColor = light_model (color);	
	//gl_FragColor = color ;
}
